package cn.aopmin.utils;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Json工具类
 * @author 白豆五
 * @since 2025/3/12
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE) // 构造器私有化
public class JsonUtils {

    private static final ObjectMapper OBJECT_MAPPER = SpringUtil.getBean(ObjectMapper.class);

    /**
     *  获取ObjectMapper
     * @return ObjectMapper对象
     */
    public static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }

    /**
     * 将对象转为json字符串
     * @param object 对象
     * @return json字符串
     */
    public static String toJsonString(Object object) {
        if (ObjectUtil.isNull(object)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为对象
     * @param text json字符串
     * @param clazz 对象类型
     * @return 对象
     */
    public static <T> T parseObject(String text, Class<T> clazz) {
        if (StringUtils.isBlank(text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json数组转为对象
     * @param bytes json字节数组
     * @param clazz 对象类型
     * @return 对象
     */
    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
        if (ArrayUtil.isEmpty(bytes)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(bytes, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为对象
     * @param text json字符串
     * @param typeReference 对象类型
     * @return 对象
     */
    public static <T> T parseObject(String text, TypeReference<T> typeReference) {
        if (StringUtils.isBlank(text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, typeReference);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为Map
     * @param text json字符串
     * @return Map
     */
    public static Dict parseMap(String text) {
        if (StringUtils.isBlank(text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory()
                    .constructType(Dict.class));
        } catch (MismatchedInputException e) {
            // 类型不匹配说明不是json
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为List<Map>
     * @param text json字符串
     * @return List<Map>
     */
    public static List<Dict> parseArrayMap(String text) {
        if (StringUtils.isBlank(text)) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory()
                    .constructCollectionType(List.class,
                            Dict.class));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为List<T>
     * @param text json字符串
     * @param clazz 对象类型
     * @return List<T>
     */
    public static <T> List<T> parseArray(String text, Class<T> clazz) {
        if (StringUtils.isEmpty(text)) {
            return new ArrayList<>();
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory()
                    .constructCollectionType(List.class,
                            clazz));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json字符串转为对象
     * @param str json字符串
     * @param clz 对象类型
     * @return 对象
     */
    public static <T> T toObj(String str, Class<T> clz) {
        try {
            return OBJECT_MAPPER.readValue(str, clz);
        } catch (JsonProcessingException e) {
            throw new UnsupportedOperationException(e);
        }
    }

    /**
     * 将json字符串转为对象
     * @param str json字符串
     * @param clz 对象类型
     * @return 对象
     */
    public static <T> T toObj(String str, TypeReference<T> clz) {
        try {
            return OBJECT_MAPPER.readValue(str, clz);
        } catch (JsonProcessingException e) {
            throw new UnsupportedOperationException(e);
        }
    }

    /**
     * 将对象转为json字符串
     * @param t 对象
     * @return json字符串
     */
    public static String toStr(Object t) {
        try {
            return OBJECT_MAPPER.writeValueAsString(t);
        } catch (Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }

    /**
     * 将json字符串转为List<T>
     * @param str json字符串
     * @param clz 对象类型
     * @return List<T>
     */
    public static <T> List<T> toList(String str, Class<T> clz) {
        try {
            return OBJECT_MAPPER.readValue(str, new TypeReference<List<T>>() {
            });
        } catch (JsonProcessingException e) {
            throw new UnsupportedOperationException(e);
        }
    }

    /**
     * 将json字符串转为JsonNode
     * @param str json字符串
     * @return JsonNode
     */
    public static JsonNode toJsonNode(String str) {
        try {
            return OBJECT_MAPPER.readTree(str);
        } catch (JsonProcessingException e) {
            throw new UnsupportedOperationException(e);
        }
    }

    /**
     * 将JsonNode转为对象
     * @param node JsonNode
     * @param clz 对象类型
     * @return 对象
     */
    public static <T> T nodeToValue(JsonNode node, Class<T> clz) {
        try {
            return OBJECT_MAPPER.treeToValue(node, clz);
        } catch (JsonProcessingException e) {
            throw new UnsupportedOperationException(e);
        }
    }

}